import { destroyNode, getRootNode } from '@/utils/dom';

import { Block } from '@tarojs/components';
import { render } from '@tarojs/react';
import { FormElement, TaroElement, TaroRootElement, document } from '@tarojs/runtime';
import {
    ForwardRefRenderFunction,
    ReactNode,
    forwardRef,
    useImperativeHandle,
    useEffect,
    useRef,
    useState
} from 'react';
const PENDING = 'pending';
const CREATED = 'created';
export interface RootPortalProps {
    visible?: boolean;
    children: ReactNode; // 需要穿梭到根组件节点的元素
    rootId?: string;
}
export type RootPortalRef = {
    destory: () => void;
};
const RootPortal: ForwardRefRenderFunction<RootPortalRef, RootPortalProps> = function (
    { children, visible, rootId = 'weapp-page-root' },
    ref
) {
    const viewRef = useRef<TaroElement | TaroRootElement | FormElement | null>(null);
    const nodeRef = useRef<any>(null);
    const isAdd = useRef(false);
    const [status, setStatus] = useState(PENDING);
    useEffect(() => {
        if (visible && status === PENDING) {
            setStatus(CREATED);
        }
    }, [status, visible]);
    useEffect(() => {
        if (!viewRef.current) {
            viewRef.current = document.createElement('div');
        }
        if (!nodeRef.current) {
            nodeRef.current = getRootNode(rootId);
        }
        if (status === CREATED) {
            render(children, viewRef.current, () => {
                if (!isAdd.current) {
                    isAdd.current = true;
                    viewRef.current && nodeRef.current.appendChild(viewRef.current);
                }
            });
        }

        return () => {
            status === CREATED && destory();
        };
    }, [status]);

    useEffect(() => {
        if (isAdd.current && viewRef.current) {
            render(children, viewRef.current, () => {});
        }
    }, [children]);

    const destory = () => {
        setStatus(PENDING);
        isAdd.current = false;
        viewRef.current && destroyNode(viewRef.current);
    };

    useImperativeHandle(ref, () => ({
        destory
    }));

    return <Block />;
};

const KRootPortal = forwardRef(RootPortal);

export default KRootPortal;
